unit uFormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  uPluginIntf, StdCtrls, Dialogs, ComCtrls, ImgList,
  DrcpSvc;

type
  TForm_Main = class(TForm,IPluginable)
    Label1: TLabel;
    Label2: TLabel;
    Edit_Id: TEdit;
    Label4: TLabel;
    ComboBox_Type: TComboBox;
    Label5: TLabel;
    Edit_Name: TEdit;
    Button_Update: TButton;
    Button_Delete: TButton;
    Button_Refresh: TButton;
    TreeView1: TTreeView;
    Button2: TButton;
    Label3: TLabel;
    ComboBox_Module: TComboBox;
    ImageList1: TImageList;
    procedure Button_RefreshClick(Sender: TObject);
    procedure Button_DeleteClick(Sender: TObject);
    procedure TreeView1Click(Sender: TObject);
    procedure ComboBox_TypeChange(Sender: TObject);
    procedure Button_UpdateClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    FSoapAddr : string;
    FSoap : DrcpService;
    { Private declarations }


    procedure LoadModuleList;

    procedure ClearFunctionTree;
    //load tree
    procedure LoadFuncTree;
    procedure LoadChildrenNode(ATree : TTreeView;ANode : TTreeNode; AAllFuncs : TStrings; AFunctionId : string);
    procedure GetFuncChildren(AAllFuncs : TStrings; AParentId : String; VChildrenIds : TStrings);

    procedure ClearListWithObject(AList : TStrings);
  protected
    FModeCreateNew : Boolean;
    FPlugin : IPlugin;

    procedure SetPlugin(APlugin : IPlugin);
    function GetPlugin:IPlugin;

    procedure Init;
  public

    { Public declarations }
    property Plugin : IPlugin read GetPlugin write SetPlugin;
  end;

implementation

{$R *.dfm}

procedure TForm_Main.Init;
begin

  //how to get soap address by context variable, see more RS_xxx by CTL + LeftClick
  FSoapAddr := Plugin.Variable[RS_DEFAULT_CONTAINER_SOAP_ADDR];
  FSoap := GetDrcpService(false,FSoapAddr);

  //how to get initialzation info
  //Plugin.InitString can be any string, strore in db [module.initstring]

  LoadModuleList;
  LoadFuncTree;
end;

procedure TForm_Main.Button_RefreshClick(Sender: TObject);
begin
  LoadFuncTree;
end;

procedure TForm_Main.Button_DeleteClick(Sender: TObject);
var
  lFunc : Function_;
  lFuncs : ArrayOf_tns2_Function;
begin
  lFunc := Function_(TreeView1.Selected.Data);
  lFuncs := FSoap.Function_GetChildren(lFunc.id);
  if Length(lFuncs) > 0 then
  begin
    ShowMessage('The function is not empty.');
    Exit;
  end;

  FSoap.Function_Delete(lFunc.id);
  FSoap.FunctionModule_Delete(lFunc.id);

  LoadFuncTree;
end;

procedure TForm_Main.LoadFuncTree;
var
  I : integer;
  lRootNode : TTreeNode;
  lFunc : Function_;
  lAllFuncs : ArrayOf_tns2_Function;

  lFunctions : TStrings;

begin

  ClearFunctionTree;

  lAllFuncs := FSoap.Function_GetAll;
  //store to TStringList
  lFunctions := TStringList.Create;
  for I := 0 to Length(lAllFuncs) -1 do
  begin
    lFunc := lAllFuncs[I];
    lFunctions.AddObject(lFunc.id,lFunc);
  end;

  lFunc := FSoap.Function_GetRoot;
  lRootNode := TreeView1.Items.AddObjectFirst(nil,lFunc.name,lFunc);
  LoadChildrenNode(TreeView1,lRootNode,lFunctions,lFunc.id);


  lFunctions.Free;
end;

procedure TForm_Main.ClearListWithObject(AList: TStrings);
var
  I : integer;
begin
  for I := 0 to AList.Count -1 do
    (AList.Objects[I]).Free;

  AList.Clear;
end;

procedure TForm_Main.ClearFunctionTree;
var
  i : integer;
  lfunc : Function_;
begin

  for i := 0 to TreeView1.Items.Count - 1 do
  begin
    lfunc := Function_(TreeView1.Items[i].Data);
    lfunc.Free;
  end;

  TreeView1.Items.Clear;

end;

procedure TForm_Main.GetFuncChildren(AAllFuncs: TStrings;
  AParentId: String; VChildrenIds: TStrings);
var
  I : integer;
  lFunc : Function_;
begin

  for I := 0 to AAllFuncs.Count - 1 do
  begin
    lFunc := Function_(AAllFuncs.Objects[I]);
    if lFunc.parentId = AParentId then
      VChildrenIds.AddObject(lFunc.id,lFunc);
  end;

end;

procedure TForm_Main.LoadChildrenNode(ATree: TTreeView; ANode: TTreeNode; AAllFuncs : TStrings;
  AFunctionId: string);
var
  lFunc : Function_;
  lChildren : TStrings;
  i : integer;
  lcnode : TTreeNode;
begin

  lChildren := TStringList.Create;
  GetFuncChildren(AAllFuncs,AFunctionId,lChildren);

  for i := 0 to lChildren.Count -1 do
  begin
    lFunc := Function_(lChildren.Objects[I]);

    lcnode:= ATree.Items.AddChildObject(ANode,lFunc.name,lFunc);

    if UpperCase(lFunc.typeId) = UpperCase('module') then
    begin
      lcnode.ImageIndex := 1;
      lcnode.SelectedIndex := 1;
    end
    else
    begin
      lcnode.ImageIndex := 0;
      lcnode.SelectedIndex := 0;
    end;

    LoadChildrenNode(ATree,lcnode, AAllFuncs,lFunc.id);
  end;
  

  lChildren.Free;
end;

procedure TForm_Main.LoadModuleList;
var
  I : integer;
  lModule : Module;
  lAllModules : ArrayOf_tns2_Module;
begin

  ClearListWithObject(ComboBox_Module.Items);

  lAllModules := FSoap.Module_GetAll();
  for I := 0 to Length(lAllModules) -1 do
  begin
    lModule := lAllModules[I];
    ComboBox_Module.Items.AddObject(lModule.name,lModule);
  end;

end;

procedure TForm_Main.TreeView1Click(Sender: TObject);
var
  lFunc : Function_;
  lModule : Module;
begin
  lFunc := Function_(TreeView1.Selected.Data);

  Edit_Id.Text := lFunc.id;
  Edit_Name.Text := lFunc.name;
  ComboBox_Type.ItemIndex := ComboBox_Type.Items.IndexOf(lFunc.typeId);
  ComboBox_TypeChange(self);

  if lFunc.typeId = 'module' then
  begin
    lModule := nil;
    lModule := FSoap.FunctionModule_GetModuleByFunctionId(lFunc.id);
    if lModule <> nil then
      ComboBox_Module.ItemIndex := ComboBox_Module.Items.IndexOf(lModule.name);
  end;

end;

procedure TForm_Main.ComboBox_TypeChange(Sender: TObject);
begin
  ComboBox_Module.Enabled := (ComboBox_Type.Text = 'module');
  if not ComboBox_Module.Enabled then
    ComboBox_Module.ItemIndex := -1;
end;

procedure TForm_Main.Button_UpdateClick(Sender: TObject);
var
  lFunc : Function_;
  lModule : Module;
  lFunctionModule : FunctionModule;
begin
  if (ComboBox_Type.Text = 'module') and (ComboBox_Module.ItemIndex < 0) then
  begin
    ShowMessage('choose a module before save.');
    exit;
  end;

  lFunc := Function_(TreeView1.Selected.Data);

  lFunc.name := Edit_Name.Text;
  lFunc.typeId := ComboBox_Type.Text;

  FSoap.Function_Update(lFunc);

  TreeView1.Selected.Text := lFunc.name;

  //set module to this function
  if lFunc.typeId = 'module' then
  begin
    lFunctionModule := FunctionModule.Create;
    lFunctionModule.id := lFunc.id;

    lModule := Module(ComboBox_Module.Items.Objects[ComboBox_Module.ItemIndex]);
    lFunctionModule.moduleId := lModule.id;
    FSoap.FunctionModule_SaveOrUpdate(lFunctionModule);
  end
  else
    FSoap.FunctionModule_Delete(lFunc.id);//delete if it is not module

  LoadFuncTree;  
end;

procedure TForm_Main.Button2Click(Sender: TObject);
var
  lSelFunc,
  lFunc : Function_;

  lNode : TTreeNode;
begin
  lSelFunc := Function_(TreeView1.Selected.Data);
  if lSelFunc = nil then
  begin
    ShowMessage('no item selected.');
    Exit;
  end;

  lFunc := Function_.Create;
  lFunc.parentId := lSelFunc.id;
  lFunc.name := 'name';
  lFunc.typeId := 'normal';

  Edit_Name.Text := lFunc.name;
  ComboBox_Type.ItemIndex := ComboBox_Type.Items.IndexOf(lFunc.typeId);

  //update DB
  lFunc.id := FSoap.Function_Save(lFunc);

  //update UI
  Edit_Id.Text := lFunc.id;
  lNode := TreeView1.Items.AddChildObject(TreeView1.Selected,lFunc.name,lFunc);

  TreeView1.Select(lNode);
end;

function TForm_Main.GetPlugin: IPlugin;
begin
  Result := FPlugin;
end;

procedure TForm_Main.SetPlugin(APlugin: IPlugin);
begin
  FPlugin := APlugin;

  Init;
end;

end.

